package field

import (
	"gitee.com/yanwc/net/utils"
)

type (
	U1    uint8
	U1Raw [1]byte

	I1    int8
	I1Raw [1]byte

	U2    uint16
	U2Raw [1]byte

	I2    int16
	I2Raw [2]byte

	U4    uint32
	U4Raw [4]byte

	I4    int32
	I4Raw [4]byte

	U6    uint64
	U6Raw [6]byte
)

func NumberTypeToRaw[T ~uint8 | ~int8 | ~uint16 | int16 | ~uint32 | int32 | ~uint64 | ~int64](t T) (out []byte) {
	copy(out[:], utils.NumberToBytesWithBigEndian(t))
	return
}

func ChToRaw(t string) (out []byte) {
	return utils.StringToBytes(t, len([]rune(t)))
}

func RawToNumberType[T ~uint8 | ~int8 | ~uint16 | int16 | ~uint32 | int32 | ~uint64 | ~int64](data []byte) T {
	return utils.BytesToNumber[T](data[:])
}

type HeaderPacketRaw struct {
	CommandWord   CommandWordRaw
	SerialNumber  SerialNumberRaw
	Property      PropertyRaw
	ContentLength U2Raw
}

type HeaderPacket struct {
	CommandWord   CommandWord
	SerialNumber  SerialNumber
	Property      Property
	ContentLength ContentLength
}

func (hp HeaderPacket) Slice() (out []byte) {
	out = append(out, hp.CommandWord.Raw().Slice()...)
	out = append(out, hp.SerialNumber.Raw().Slice()...)
	out = append(out, hp.Property.Raw().Slice()...)
	return
}

type BasePacketRaw struct {
	F1Raw  utils.TimeStampUTCRaw
	F5Raw  CSQRaw
	F7Raw  TemperatureRaw
	F8Raw  YktHelmetFaultRaw_1
	F9Raw  StatusBit32Raw
	F13Raw VoltageVRaw
	F15Raw YktHelmetFaultRaw_2
	F16Raw ProtocolVersionRaw
	F17Raw BatteryPercentageRaw
	F18Raw U1Raw // 保留
	F19Raw IMEIRaw
	F27Raw IMEIRaw
}

type BasePacket struct {
	F1  utils.TimeStampUTC
	F5  CSQ
	F7  Temperature
	F8  YktHelmetFault_1
	F9  StatusBit32
	F13 VoltageV
	F15 YktHelmetFault_2
	F16 ProtocolVersion
	F17 BatteryPercentage
	F18 Reserve1Byte // 保留
	F19 IMEI
	F27 IMSI
}

func (bp BasePacket) Slice() ([]byte, error) {
	imei, err := bp.F19.Raw()
	if err != nil {
		return nil, err
	}

	imsi, err := bp.F27.Raw()
	if err != nil {
		return nil, err
	}

	out := make([]byte, 0)
	out = append(out, bp.F1.Raw().Slice()...)
	out = append(out, bp.F5.Raw().Slice()...)
	out = append(out, bp.F7.Raw().Slice()...)
	out = append(out, bp.F8.Raw().Slice()...)
	out = append(out, bp.F9.Raw().Slice()...)
	out = append(out, bp.F13.Raw().Slice()...)
	out = append(out, bp.F15.Raw().Slice()...)
	out = append(out, bp.F16.Raw().Slice()...)
	out = append(out, bp.F17.Raw().Slice()...)
	out = append(out, bp.F18[:]...)
	out = append(out, imei.Slice()...)
	out = append(out, imsi.Slice()...)
	return out, nil
}
